package com.songshuang.myutilsboot.stlf.core;

import java.util.List;

final class LinearRegression {
    private LinearRegression() {}

    // 多元线性回归: 最小二乘，构造 X'X b = X'y，返回系数 b（含截距项）
    static double[] fit(double[][] x, double[] y, int rows, int cols) {
        // x: 1..rows, 1..cols; y: 1..rows。维度对齐C++实现风格
        double[][] xtx = new double[cols + 1][cols + 1];
        double[] xty = new double[cols + 1];

        for (int i = 1; i <= rows; i++) {
            for (int j = 0; j <= cols; j++) {
                double xij = (j == 0) ? 1.0 : x[i][j];
                xty[j] += xij * y[i];
                for (int k = j; k <= cols; k++) {
                    double xik = (k == 0) ? 1.0 : x[i][k];
                    xtx[j][k] += xij * xik;
                }
            }
        }
        // 对称填充
        for (int j = 0; j <= cols; j++) {
            for (int k = 0; k < j; k++) xtx[j][k] = xtx[k][j];
        }
        // 高斯消元求解
        return gauss(xtx, xty, cols);
    }

    static double predict(double[] b, double[] x) {
        double sum = b[0];
        for (int j = 1; j < b.length; j++) sum += b[j] * x[j];
        return sum;
    }

    private static double[] gauss(double[][] a, double[] b, int n) {
        int N = n + 1;
        for (int k = 0; k <= n; k++) {
            int pivot = k;
            for (int i = k + 1; i <= n; i++) {
                if (Math.abs(a[i][k]) > Math.abs(a[pivot][k])) pivot = i;
            }
            if (pivot != k) {
                double[] tmp = a[k]; a[k] = a[pivot]; a[pivot] = tmp;
                double tb = b[k]; b[k] = b[pivot]; b[pivot] = tb;
            }
            double akk = a[k][k];
            if (Math.abs(akk) < 1e-12) akk = 1e-12;
            for (int j = k; j <= n; j++) a[k][j] /= akk;
            b[k] /= akk;
            for (int i = 0; i <= n; i++) {
                if (i == k) continue;
                double factor = a[i][k];
                if (Math.abs(factor) < 1e-12) continue;
                for (int j = k; j <= n; j++) a[i][j] -= factor * a[k][j];
                b[i] -= factor * b[k];
            }
        }
        double[] x = new double[N];
        System.arraycopy(b, 0, x, 0, N);
        return x;
    }
}


